package com.xuecheng.media.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.xuecheng.media.mapper.MediaStatusMapper;
import com.xuecheng.media.model.po.MediaStatus;
import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.RemoveObjectsArgs;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author shiminghui
 * @date 2024/8/24 16:39
 * @description: 用来检测是否有文件没有上传成功, 并删除分块文件
 */
@Component
@Slf4j
public class ChunkMediaTask {

    @Autowired
    private MediaStatusMapper mediaStatusMapper;
    @Autowired
    private MinioClient minioClient;

    @Scheduled(cron = "0 0/1 * * * ?")//每分钟执行一次
    public void chunkMediaStatus() {
        //首先查询数据库
        QueryWrapper<MediaStatus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", "0");

        // 使用apply方法添加条件
        queryWrapper.apply("upload_time < DATE_SUB(NOW(), INTERVAL 10 HOUR)");

        List<MediaStatus> mediaStatuses = mediaStatusMapper.selectList(queryWrapper);

        ArrayList<String> list = new ArrayList<>();

        mediaStatuses.stream().forEach(item -> {
            //是否删除标记
            int[] ints = new int[1];
            ints[0] = 1;

            //构造查询参数
            String bucket = item.getBucket();
            String filePath = item.getFilePath();
            ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
                    .bucket(bucket)
                    .prefix(filePath)
                    .build();
            Iterable<Result<Item>> results = minioClient.listObjects(listObjectsArgs);
            //遍历每一个并删除
            results.forEach(itemResult -> {
                try {
                    Item item1 = itemResult.get();
                    list.add(item1.objectName());
                } catch (Exception e) {
                    log.error("遍历获取文件失败,桶:{},文件路径:{}", bucket, filePath);
                    ints[0] = 0;
                }
            });
            //删除分块

            List<DeleteObject> collect = list.stream().map(item1 -> {
                return new DeleteObject(item1);
            }).collect(Collectors.toList());
            //构建删除队列
            RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder()
                    .bucket(bucket)
                    .objects(collect)
                    .build();
            Iterable<Result<DeleteError>> results1 = minioClient.removeObjects(removeObjectsArgs);
            results1.forEach(item2 -> {
                try {
                    DeleteError deleteError = item2.get();//调用删除
                } catch (Exception e) {
                    log.error("删除文件失败,桶:{},文件路径:{}", bucket, filePath);
                    ints[0] = 0;
                }
            });
            //然后修改数据库数据
            if (ints[0] == 1) {//等于1说明没有出现错误
                UpdateWrapper<MediaStatus> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("id", item.getId())
                        .set("status", 2)
                        .set("delete_time", LocalDateTime.now());
                int update = mediaStatusMapper.update(item, updateWrapper);
                if (update < 0) {
                    log.error("更新信息失败,更新对象为{}", item);
                }
            }
        });


    }

}
